home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Magazin/MacEasy 19
/
Mac Magazin and MacEasy Magazine CD - Issue 19.iso
/
Online
/
HttpServerƒ
/
•Mac_Classes
/
TThread.cp
< prev
next >
Wrap
Text File
|
1996-01-03
|
8KB
|
278 lines
// TThread.cp - Macintosh Thread class object
//
// Apple Macintosh Developer Technical Support
// Written by: Vinne Moscaritolo
//
// Copyright (work in progress) Apple Computer, Inc All rights reserved.
//
// You may incorporate this sample code into your applications without
// restriction, though the sample code has been provided "AS IS" and the
// responsibility for its operation is 100% yours. However, what you are
// not permitted to do is to redistribute the source as "DSC Sample Code"
// after having made changes. If you're going to re-distribute the source,
// we require that you make it clear in the source that the code was
// descended from Apple Sample Code, but that you've made changes.
//
#include "TMacException.h"
#include "TThread.h"
#include "TNetworkException.h"
#include <strstream.h>
// ===========================================================================
// Static member variables
// ===========================================================================
Boolean TThread::fgInited = false; // is Thread class library inited
ProcessSerialNumber TThread::fgPSN; // application's PSN
ThreadTaskRef TThread::fgThreadTaskRef; // thread task ref
// ---------------------------------------------------------------------------
// DoEntry (pascal wrapper function)
// ---------------------------------------------------------------------------
// Thread manager Callback for thread entry
pascal void* TThread::DoEntry(void *arg)
{
TThread *theThread = (TThread*) arg;
void* theResult;
// try
{
theResult = theThread->Run();
}
// catch(...)
{
// stop error prop
}
// Recycle thread
theThread->Stop(theResult);
// cant get here...
ThrowMsg("TThread :DoEntry returned from dispose");
return nil;
}
// ---------------------------------------------------------------------------
// DoTermination (pascal wrapper function)
// ---------------------------------------------------------------------------
// Thread manager Callback for thread termination
pascal void TThread::DoTermination(ThreadID theID, void *arg)
{
TThread *theThread = (TThread*) arg;
theThread->fTID = kNoThreadID;
try
{
theThread->Done();
}
catch(...)
{
// all we want is to stop error propagation
}
}
// ---------------------------------------------------------------------------
// DoSwapIn (pascal wrapper function)
// ---------------------------------------------------------------------------
// Thread manager Callback for thread Swap in
pascal void TThread::DoSwapIn(ThreadID, void *arg)
{
TThread* theThread = (TThread*) arg;
theThread->fContext.Restore();
}
// ---------------------------------------------------------------------------
// DoSwapOut (pascal wrapper function)
// ---------------------------------------------------------------------------
// Thread manager Callback for thread Swap Out
pascal void TThread::DoSwapOut(ThreadID, void *arg)
{
TThread *theThread = (TThread*) arg;
theThread->fContext.Save();
}
// ---------------------------------------------------------------------------
// TThread
// ---------------------------------------------------------------------------
// Default Constructor
TThread::TThread()
{
// Check if first time to use thread package
if (!fgInited) Initialize();
// Set state
fTID = kNoThreadID;
}
// ---------------------------------------------------------------------------
// ~TThread
// ---------------------------------------------------------------------------
// Destructor
TThread::~TThread()
{
// Kill thread if it's running
Stop(0);
fTID = kNoThreadID;
}
// ---------------------------------------------------------------------------
// Start
// ---------------------------------------------------------------------------
// Setup thread for execution
void TThread::Start()
{
OSErr ErrNo;
try {
// Create thread
ThrowIfOSErr (::NewThread( kCooperativeThread, // kCooperativeThread,kPreemptiveThread
DoEntry, // thread entry proc
this, // param to entry proc
0, // Stack space
(kReadyThreadState // starting state (ready)
| kCreateIfNeeded), // try to get from pool
(void**) &fResult, // place to put quit result
&fTID)); // place to put task ID
// set terminator and thread switch procs
ThrowIfOSErr(::SetThreadSwitcher(fTID, DoSwapIn, this, true));
ThrowIfOSErr(::SetThreadSwitcher(fTID, DoSwapOut, this, false));
ThrowIfOSErr(::SetThreadTerminator(fTID, DoTermination, this));
}
catch(...){
if (fTID != kNoThreadID) {
::SetThreadTerminator(fTID, nil, nil);
::DisposeThread(fTID, nil, true);
fTID = kNoThreadID;
}
throw;
}
}
// ---------------------------------------------------------------------------
// Stop
// ---------------------------------------------------------------------------
// Stop thread execution
void TThread::Stop(void * theResult)
{
if(fTID != kNoThreadID){
ThreadID ourThread = fTID;
fTID = kNoThreadID; // this might be the last thing this thread does
::DisposeThread(ourThread,theResult, true); // so juggle the Tid
};
}
// ---------------------------------------------------------------------------
// Sleep
// ---------------------------------------------------------------------------
// Sleep Thread
void TThread::Sleep()
{
if(fTID != kNoThreadID)
ThrowIfOSErr(::SetThreadState(fTID,kStoppedThreadState,kCurrentThreadID));
}
// ---------------------------------------------------------------------------
// WakeUp
// ---------------------------------------------------------------------------
// Wake up Thread
void TThread::WakeUp()
{
ThreadState threadState;
if( (fTID != kNoThreadID)
&& (::GetThreadStateGivenTaskRef(fgThreadTaskRef, fTID,&threadState) != noErr)
&& (threadState == kStoppedThreadState))
::SetThreadReadyGivenTaskRef(fgThreadTaskRef, fTID);
}
// ---------------------------------------------------------------------------
// Yield
// ---------------------------------------------------------------------------
// Yield time to next thread
void TThread::Yield()
{
::YieldToAnyThread();
}
// ---------------------------------------------------------------------------
// Run
// ---------------------------------------------------------------------------
// default thread Run
void* TThread::Run()
{
while(true) {
Yield();
}
return nil;
}
// ---------------------------------------------------------------------------
// Done
// ---------------------------------------------------------------------------
// default thread Done
void TThread::Done()
{
}
// ---------------------------------------------------------------------------
// Allocate (static public)
// ---------------------------------------------------------------------------
// Allocate memory for Thread manager
void TThread::Allocate(short numToCreate, Size stackSize)
{
ThrowIfOSErr(::CreateThreadPool(kCooperativeThread, numToCreate, stackSize));
}
// ---------------------------------------------------------------------------
// Initialize
// ---------------------------------------------------------------------------
// Will run when first thread is started
void TThread::Initialize()
{
// is the Thread Manager running ?
/* if (!UEnvironment::HasFeature(env_HasThreadsManager))
{
ThrowOSErr_(threadProtocolErr);
}
*/
// low-level initialisation
ThrowIfOSErr( ::GetCurrentProcess(&fgPSN));
ThrowIfOSErr( ::GetThreadCurrentTaskRef(&fgThreadTaskRef));
fgInited = true;
}